"use strict";
cc._RF.push(module, '79777kgUFNH7IobLwg8lArh', 'MapControl');
// Script/MapControl.ts

"use strict";
/**
 * @author xshu
 * @date 2019-12-07
 */
var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var _a = cc._decorator, ccclass = _a.ccclass, property = _a.property;
var MapControl = /** @class */ (function (_super) {
    __extends(MapControl, _super);
    function MapControl() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this.map = null;
        _this.scaleTime = null;
        _this.defaultScaling = 1.1;
        _this.minScale = 1;
        _this.maxScale = 3;
        _this.moveOffset = 2;
        _this.increaseRate = 10000;
        _this.fingerIncreaseRate = 1;
        _this.locked = false; // 操作锁
        _this.singleTouchCb = null; // 点击回调函数
        _this.isMoving = false; // 是否拖动地图flag
        _this.mapTouchList = []; // 触摸点列表容器
        _this.isStrict = false; // 默认为非严格模式
        return _this;
    }
    MapControl.prototype.onLoad = function () {
    };
    MapControl.prototype.start = function () {
        this.addEvent();
        this.smoothOperate(this.map, cc.Vec2.ZERO, this.defaultScaling);
    };
    MapControl.prototype.resetMap = function () {
        this.smoothOperate(this.map, cc.Vec2.ZERO, this.defaultScaling);
    };
    // 有些设备单点过于灵敏，单点操作会触发TOUCH_MOVE回调，在这里作误差值判断
    MapControl.prototype.canStartMove = function (touch) {
        var startPos = touch.getStartLocation();
        var nowPos = touch.getLocation();
        // 有些设备单点过于灵敏，单点操作会触发TOUCH_MOVE回调，在这里作误差值判断
        return (Math.abs(nowPos.x - startPos.x) > this.moveOffset
            || Math.abs(nowPos.y - startPos.y) > this.moveOffset);
    };
    MapControl.prototype.addEvent = function () {
        this.node.on(cc.Node.EventType.TOUCH_MOVE, function (event) {
            var _this = this;
            if (this.locked)
                return;
            var touches = event.getTouches(); // 获取所有触摸点
            if (this.isStrict) { // 严格模式下过滤掉初始点击位置不在目标节点范围内的触摸点
                touches
                    .filter(function (v) {
                    var startPos = cc.v2(v.getStartLocation()); // 触摸点最初的位置
                    var worldPos = _this.node.convertToWorldSpaceAR(cc.Vec2.ZERO);
                    var worldRect = cc.rect(worldPos.x - _this.node.width / 2, worldPos.y - _this.node.height / 2, _this.node.width, _this.node.height);
                    return worldRect.contains(startPos);
                })
                    .forEach(function (v) {
                    var intersection = _this.mapTouchList.filter(function (v1) { return v1.id === v.getID(); });
                    if (intersection.length === 0)
                        _this.mapTouchList[_this.mapTouchList.length] = ({ id: v.getID(), touch: v });
                });
                touches = this.mapTouchList.map(function (v) { return v.touch; });
            }
            if (touches.length >= 2) {
                // cc.log('multi touch');
                // multi touch
                this.isMoving = true;
                var touch1 = touches[0];
                var touch2 = touches[1];
                var delta1 = cc.v2(touch1.getDelta());
                var delta2 = cc.v2(touch2.getDelta());
                var touchPoint1 = this.map.convertToNodeSpaceAR(cc.v2(touch1.getLocation()));
                var touchPoint2 = this.map.convertToNodeSpaceAR(cc.v2(touch2.getLocation()));
                var distance = touchPoint1.sub(touchPoint2);
                var rateV2 = cc.v2(this.fingerIncreaseRate, this.fingerIncreaseRate);
                var delta = delta1.sub(delta2).scale(rateV2);
                var scale = 1;
                if (Math.abs(distance.x) > Math.abs(distance.y)) {
                    scale = (distance.x + delta.x) / distance.x * this.map.scaleX;
                }
                else {
                    scale = (distance.y + delta.y) / distance.y * this.map.scaleY;
                }
                var pos = touchPoint2.add(cc.v2(distance.x / 2, distance.y / 2));
                this.smoothOperate(this.map, pos, scale);
            }
            else if (touches.length === 1) {
                // cc.log('single touch');
                // single touch
                if (this.isMoving || this.canStartMove(touches[0])) {
                    this.isMoving = true;
                    var dir = cc.v2(touches[0].getDelta());
                    this.dealMove(dir, this.map, this.node);
                }
            }
        }, this);
        this.node.on(cc.Node.EventType.TOUCH_END, function (event) {
            if (this.locked)
                return;
            var touches = this.isStrict ? this.mapTouchList : event.getTouches();
            if (touches.length <= 1) {
                if (!this.isMoving) {
                    var worldPos = cc.v2(event.getLocation());
                    var nodePos = this.map.convertToNodeSpaceAR(worldPos);
                    this.dealSelect(nodePos);
                }
                this.isMoving = false; // 当容器中仅剩最后一个触摸点时将移动flag还原
            }
            ;
            if (this.isStrict)
                this.removeTouchFromContent(event, this.mapTouchList);
        }, this);
        this.node.on(cc.Node.EventType.TOUCH_CANCEL, function (event) {
            if (this.locked)
                return;
            var touches = this.isStrict ? this.mapTouchList : event.getTouches();
            // 当容器中仅剩最后一个触摸点时将移动flag还原
            if (touches.length <= 1)
                this.isMoving = false;
            if (this.isStrict)
                this.removeTouchFromContent(event, this.mapTouchList);
        }, this);
        this.node.on(cc.Node.EventType.MOUSE_WHEEL, function (event) {
            if (this.locked)
                return;
            var worldPos = cc.v2(event.getLocation());
            var scrollDelta = event.getScrollY();
            var scale = (this.map.scale + (scrollDelta / this.increaseRate));
            var target = this.map;
            var pos = target.convertToNodeSpaceAR(worldPos);
            this.smoothOperate(target, pos, scale);
        }, this);
    };
    MapControl.prototype.removeTouchFromContent = function (event, content) {
        var eventToucheIDs = event['getTouches']().map(function (v) { return v.getID(); });
        for (var len = content.length, i = len - 1; i >= 0; --i) {
            if (eventToucheIDs.indexOf(content[i].id) > -1)
                content.splice(i, 1); // 删除触摸
        }
    };
    MapControl.prototype.smoothOperate = function (target, pos, scale) {
        // 放大缩小
        if (this.minScale <= scale && scale <= this.maxScale) {
            // 当前缩放值与原来缩放值之差
            var deltaScale = scale - target.scaleX;
            // 当前点击的坐标与缩放值差像乘
            var gapPos = pos.scale(cc.v2(deltaScale, deltaScale));
            // 当前node坐标位置减去点击 点击坐标和缩放值的值
            var _pos = target.position.sub(cc.v3(gapPos.x, gapPos.y, 0));
            var mapPos = cc.v2(_pos.x, _pos.y); //target.position.sub(gapPos);
            // 获取速率的小数后几位，防止速率过小时取整直接舍弃掉了变化
            var rateStr = this.fingerIncreaseRate.toString();
            var digit = rateStr.split('.')[1] ? rateStr.split('.')[1].length : 0;
            var rate = Math.pow(10, 2 + digit);
            scale = Math.floor(scale * rate) / rate;
            target.scale = scale;
            this.dealScalePos(mapPos, target);
        }
        else {
            scale = cc.misc.clampf(scale, this.minScale, this.maxScale);
        }
        // render ui
        if (cc.isValid(this.scaleTime))
            this.scaleTime.string = Math.floor(scale * 100) + "%";
    };
    MapControl.prototype.dealScalePos = function (pos, target) {
        if (target.scale === 1) {
            pos = cc.Vec2.ZERO;
        }
        else {
            var worldPos = this.node.convertToWorldSpaceAR(pos);
            var nodePos = this.node.convertToNodeSpaceAR(worldPos);
            var edge = this.calculateEdge(target, this.node, nodePos);
            if (edge.left > 0) {
                pos.x -= edge.left;
            }
            if (edge.right > 0) {
                pos.x += edge.right;
            }
            if (edge.top > 0) {
                pos.y += edge.top;
            }
            if (edge.bottom > 0) {
                pos.y -= edge.bottom;
            }
        }
        target.position = cc.v3(pos.x, pos.y, 0);
    };
    MapControl.prototype.dealMove = function (dir, map, container) {
        var worldPos = map.convertToWorldSpaceAR(cc.Vec2.ZERO);
        var nodePos = container.convertToNodeSpaceAR(worldPos);
        nodePos.x += dir.x;
        nodePos.y += dir.y;
        var edge = this.calculateEdge(map, container, nodePos);
        if (edge.left <= 0 && edge.right <= 0) {
            map.x += dir.x;
        }
        if (edge.top <= 0 && edge.bottom <= 0) {
            map.y += dir.y;
        }
    };
    MapControl.prototype.dealSelect = function (nodePos) {
        cc.log("click map on (" + nodePos.x + ", " + nodePos.y + ")");
        // do sth
        if (this.singleTouchCb)
            this.singleTouchCb(nodePos);
    };
    // 计算map的四条边距离容器的距离，为负代表超出去
    MapControl.prototype.calculateEdge = function (target, container, nodePos) {
        // distance to the edge when anchor is (0.5, 0.5)
        var horizontalDistance = (container.width - target.width * target.scaleX) / 2;
        var verticalDistance = (container.height - target.height * target.scaleY) / 2;
        var left = horizontalDistance + nodePos.x;
        var right = horizontalDistance - nodePos.x;
        var top = verticalDistance - nodePos.y;
        var bottom = verticalDistance + nodePos.y;
        return { left: left, right: right, top: top, bottom: bottom };
    };
    /**
     * @brief 设置是否严格模式，如果为严格模式，则会过滤不在目标身上的触摸点， 反之不作处理
     *              默认为非严格模式
     * @param isStrict
     */
    MapControl.prototype.setStrictPattern = function (isStrict) {
        this.isStrict = isStrict;
    };
    MapControl.prototype.getStrictPattern = function () {
        return this.isStrict;
    };
    __decorate([
        property({
            type: cc.Node,
            tooltip: '目标节点'
        })
    ], MapControl.prototype, "map", void 0);
    __decorate([
        property(cc.Label)
    ], MapControl.prototype, "scaleTime", void 0);
    __decorate([
        property({
            tooltip: '图片初始缩放'
        })
    ], MapControl.prototype, "defaultScaling", void 0);
    __decorate([
        property({
            tooltip: '图片缩放最小scale'
        })
    ], MapControl.prototype, "minScale", void 0);
    __decorate([
        property({
            tooltip: '图片缩放最大scale'
        })
    ], MapControl.prototype, "maxScale", void 0);
    __decorate([
        property({
            tooltip: '单点触摸容忍误差'
        })
    ], MapControl.prototype, "moveOffset", void 0);
    __decorate([
        property({
            tooltip: '滚轮缩放比率'
        })
    ], MapControl.prototype, "increaseRate", void 0);
    __decorate([
        property({
            displayName: '双指缩放速率',
            max: 10,
            min: 0.001,
        })
    ], MapControl.prototype, "fingerIncreaseRate", void 0);
    __decorate([
        property
    ], MapControl.prototype, "isStrict", void 0);
    MapControl = __decorate([
        ccclass
    ], MapControl);
    return MapControl;
}(cc.Component));
module.exports = MapControl;

cc._RF.pop();